\chapter{QSslSocket} (未完成)

QSslSocket 类为客户端和服务端提供了一个 SSL 加密的套接字。

\begin{tabular}{|r|l|}
	\hline
	属性 & 方法 \\
	\hline
	头文件 & \#include <QSslSocket>\\      
	\hline
	qmake & QT += network\\      
	\hline
	引入 &	Qt4.3 \\ 
	\hline
	继承自 	& QTcpSocket \\
	\hline
\end{tabular}

该类最初在 Qt 4.3 版本引入。

您可以在 QSslSocket\_Obsolete 界面找到过时的成员函数介绍。

\begin{notice}
该类所有的函数都是可重入的。
\end{notice}

\section{公共成员类型}

\begin{tabular}[l]{|l|m{30em}|}
\hline 
类型 &	属性\\ 
\hline 
enum 	&PeerVerifyMode \{ VerifyNone, QueryPeer, VerifyPeer, AutoVerifyPeer \} \\ 
\hline  
enum &	SslMode \{ UnencryptedMode, SslClientMode, SslServerMode \} \\ 
	\hline
\end{tabular}


\section{公共成员函数}

\begin{longtable}[l]{|l|m{30em}|}
\hline 
类型 &	函数名\\ 
\hline 
& QSslSocket(QObject *parent = nullptr) \\ 
\hline
virtual &	$\sim$QSslSocket() \\ 
\hline
void 	&abort() \\ 
\hline
void &	connectToHostEncrypted(const QString \&hostName, quint16 port, QIODevice::OpenMode mode = ReadWrite, QAbstractSocket::NetworkLayerProtocol protocol = AnyIPProtocol) \\ 
\hline
void &	connectToHostEncrypted(const QString \&hostName, quint16 port, const QString \&sslPeerName, QIODevice::OpenMode mode = ReadWrite, QAbstractSocket::NetworkLayerProtocol protocol = AnyIPProtocol) \\ 
\hline
qint64 	&encryptedBytesAvailable() const \\ 
\hline
qint64 &	encryptedBytesToWrite() const \\ 
\hline
bool &	flush() \\ 
\hline
void &	ignoreSslErrors(const QList<QSslError> \&errors) \\ 
\hline
bool 	&isEncrypted() const \\ 
\hline
QSslCertificate &	localCertificate() const \\ 
\hline
QList<QSslCertificate> &	localCertificateChain() const \\ 
\hline
QSslSocket::SslMode &	mode() const \\ 
\hline
QVector<QOcspResponse> &	ocspResponses() const \\ 
\hline
QSslCertificate &	peerCertificate() const \\ 
\hline 
QList<QSslCertificate> 	&peerCertificateChain() const \\ 
\hline
int 	&peerVerifyDepth() const \\ 
\hline
QSslSocket::PeerVerifyMode &peerVerifyMode() const \\ 
\hline
QString &	peerVerifyName() const \\ 
\hline 
QSslKey &	privateKey() const \\ 
\hline
QSsl::SslProtocol &	protocol() const \\ 
\hline
QSslCipher 	&sessionCipher() const \\ 
\hline 
QSsl::SslProtocol 	&sessionProtocol() const \\
\hline
void &	setLocalCertificate(const QSslCertificate \&certificate) \\ 
\hline
void 	&setLocalCertificate(const QString \&path, QSsl::EncodingFormat format = QSsl::Pem) \\ 
\hline
void &	setLocalCertificateChain(const QList<QSslCertificate> \&localChain) \\
\hline
void &	setPeerVerifyDepth(int depth) \\ 
\hline
void &	setPeerVerifyMode(QSslSocket::PeerVerifyMode mode) \\
\hline
void &	setPeerVerifyName(const QString \&hostName) \\ 
\hline
void &	setPrivateKey(const QSslKey \&key) \\ 
\hline 
void 	&setPrivateKey(const QString \&fileName, QSsl::KeyAlgorithm algorithm = QSsl::Rsa, QSsl::EncodingFormat format = QSsl::Pem, const QByteArray \&passPhrase = QByteArray()) \\ 
\hline
void &	setProtocol(QSsl::SslProtocol protocol) \\ 
\hline
void &	setSslConfiguration(const QSslConfiguration \&configuration) \\ 
\hline
QSslConfiguration &	sslConfiguration() const \\ 
\hline
QList<QSslError> 	&sslHandshakeErrors() const \\ 
\hline
bool 	&waitForEncrypted(int msecs = 30000) \\ 
\hline 
\end{longtable}

\section{重写公共成员函数}

\begin{longtable}[l]{|l|m{30em}|}
\hline 
类型 &	函数名\\ 
\hline 
virtual bool &	atEnd() const override \\ 
\hline
virtual qint64 	&bytesAvailable() const override \\ 
\hline
virtual qint64 &	bytesToWrite() const override \\ 
\hline
virtual bool &	canReadLine() const override \\ 
\hline
virtual void &	close() override \\
\hline
virtual void &	resume() override \\ 
\hline
virtual void &	setReadBufferSize(qint64 size) override \\ 
\hline
virtual bool &	setSocketDescriptor(qintptr socketDescriptor, QAbstractSocket::SocketState state = ConnectedState, QIODevice::OpenMode openMode = ReadWrite) override \\ 
\hline
virtual void &	setSocketOption(QAbstractSocket::SocketOption option, const QVariant \&value) override \\
\hline
virtual QVariant &	socketOption(QAbstractSocket::SocketOption option) override \\ 
\hline
virtual bool &	waitForBytesWritten(int msecs = 30000) override \\ 
\hline
virtual bool &	waitForConnected(int msecs = 30000) override \\ 
\hline
virtual bool &	waitForDisconnected(int msecs = 30000) override \\ 
\hline
virtual bool &	waitForReadyRead(int msecs = 30000) override \\ 
	\hline
\end{longtable}

\section{公共槽函数}

\begin{tabular}[l]{|l|m{30em}|}
	\hline 
	类型 &	函数名\\ 
	\hline 
	void &	ignoreSslErrors() \\ 
	\hline
	void &	startClientEncryption() \\ 
	\hline
	void &	startServerEncryption() \\ 
	\hline
\end{tabular}

\section{信号}

\begin{tabular}[l]{|l|m{39em}|}
	\hline 
	类型 &	函数名\\ 
	\hline 
	void 	&encrypted() \\ 
	\hline
	void &	encryptedBytesWritten(qint64 written) \\ 
	\hline
	void &	modeChanged(QSslSocket::SslMode mode) \\ 
	\hline
	void &	newSessionTicketReceived() \\ 
	\hline
	void &	peerVerifyError(const QSslError \&error) \\ 
	\hline
	void &	preSharedKeyAuthenticationRequired(QSslPreSharedKeyAuthenticator *authenticator) \\
	\hline
	void &	sslErrors(const QList<QSslError> \&errors) \\ 
	\hline
\end{tabular}


%%%%%%%%%%%%


\section{静态成员函数}

\begin{tabular}[l]{|l|m{39em}|}
	\hline 
	类型 &	函数名\\ 
	\hline 
	long &	sslLibraryBuildVersionNumber() \\ 
	\hline
	QString &	sslLibraryBuildVersionString() \\ 
	\hline
	long 	&sslLibraryVersionNumber() \\
	\hline
	QString &	sslLibraryVersionString() \\ 
	\hline
	bool &	supportsSsl() \\ 
	\hline 
\end{tabular}

\section{重写保护成员函数}

\begin{tabular}[l]{|l|m{39em}|}
	\hline 
	类型 &	函数名\\ 
	\hline 
类型 	 & 函数名 \\ 
\hline 
virtual qint64 &	readData(char *data, qint64 maxlen) override \\ 
\hline 
virtual qint64 & 	writeData(const char *data, qint64 len) override \\ 
	\hline
\end{tabular}

\section{详细介绍}

QSslSocket 能够建立一个安全的、加密的 TCP 连接，
您可以使用该连接来传输加密数据。在服务器端和客户端都可以使用它，
并且他支持现代的 SSL 协议，包括 SSL 3 和 TLS 1.2。默认情况下，
QSslSocket 仅仅使用被认为是安全的（ QSsl::SecureProtocols ） SSL 协议，
但是只要处在握手开始之前，您仍然可以调用 setProtocol() 函数来更改 SSL 协议。

在套接字进入 已连接（ConnectedState ）状态后，SSL 将在现有 TCP 流上进行加密。
有两种使用 QSslSocket 建立安全连接的简单方法：使用即时 SSL 握手，
或在未加密模式下建立连接之后的延迟 SSL 握手。

最常见的 QSslSocket 使用方法是构造一个对象后使用 connectToHostEncrypted() 
函数开启一个安全连接，
这种方法会在连接建立后开启一个即时的 SSL 握手。

\begin{cppcode}
QSslSocket *socket = new QSslSocket(this);
connect(socket, SIGNAL(encrypted()), this, SLOT(ready()));

socket->connectToHostEncrypted("imap.example.com", 993);
\end{cppcode}

与普通的 QTcpSocket 相同，若成功建立连接， QSslSocket 会依次进入 HostLookupState ，
ConnectingState 和 ConnectedState 状态。连接成功后，握手会自动开始，若握手连接成功，
QSsslSocket 将会发送 encrypted() 信号，表明该套接字已经进入加密状态并准备好使用。

请注意，在 connectToHostEncrypted() 函数执行完成返回后（即 encrypted() 信号发出之前）数据就可以立即写入套接字。
此时写入到套接字的数据将会被加入等待队列，直到 encrypted() 信号被发出。

使用延迟 SSL 握手来保护现有连接的示例是 SSL 服务器保护传入连接。

假设您继承 QTcpServer 类创建了一个 SSL 服务器类。
您需要如下例重写 QTcpServer::incomingConnection() ：
首先构造一个 QSslSocket 对象并调用 setSocketDescriptor() 函数将新的套接字描述符设置为传入的已有的套接字描述符。
然后调用 startServerEncryption() 函数初始化 SSL 握手。

\begin{cppcode}
 void SslServer::incomingConnection(qintptr socketDescriptor)
 {
     QSslSocket *serverSocket = new QSslSocket;
     if (serverSocket->setSocketDescriptor(socketDescriptor)) {
         addPendingConnection(serverSocket);
         connect(serverSocket, &QSslSocket::encrypted, this, &SslServer::ready);
         serverSocket->startServerEncryption();
     } else {
         delete serverSocket;
     }
 }
\end{cppcode}

如果出现了错误， QSslSocket 将会发出 sslErrors() 信号。在这种情况下，
如果没有采取任何操作去忽略出现的错误，该连接将会掉线。
若要出现错误后仍然继续维持连接，您可以在错误发生后的槽函数中，
或者 QSslSocket 对象构建后、尝试连接之前，调用 ignoreSslErrors() 函数。
ignoreSslErrors() 函数将允许 QSslSocket 忽略在建立对等方身份时遇到的错误。
 应谨慎使用 ignoreSslErrors() 函数忽略SSL握手期间的错误，
 因为安全连接的基本特征是应该通过成功的握手来建立它们。

连接加密后，您可以像普通的 QTcpSocket 类一样使用 QSslSocket。
当 readyRead() 信号发出后，您可以调用 read()，canReadLine() 和 readLine() 或者 
getChar() 从 QSslSocket 的内部缓冲区中读取加密数据，然后您可以调用 write() 或者 putChar() 向对等端写回数据。
 QSslSocket 将会自动将您写入的数据加密并在数据写入到对等端后发送 encryptedBytesWritten() 信号。

方便起见，QSslSocket 支持 QTcpSocket 的阻塞函数：waitForConnected()，waitForReadyRead()，
waitForBytesWritten() 和 waitForDisconnected()。它也提供了 waitForEncrypted()
 函数来在加密连接建立之前阻塞调用的线程。


\begin{cppcode}
 QSslSocket socket;
 socket.connectToHostEncrypted("http.example.com", 443);
 if (!socket.waitForEncrypted()) {
     qDebug() << socket.errorString();
     return false;
 }

 socket.write("GET / HTTP/1.0\r\n\r\n");
 while (socket.waitForReadyRead())
     qDebug() << socket.readAll().data();
\end{cppcode}

QSslSocket 提供了广泛的、易于使用的 API ，用于处理密码，私钥以及本地，
对等端和证书颁发机构（CA）证书。它也为处理握手阶段出现的错误提供了 API 支持。

以下的特性也可以被客制化：

\begin{compactitem}
\item 套接字的加密密码套件可以在握手阶段之前通过 QSslConfiguration :: setCiphers() 和 QSslConfiguration :: setDefaultCiphers() 定制。
\item 套接字的本地证书和私钥可以在握手阶段之前通过 setLocalCertificate() 和 setPrivateKey() 设置。
\item CA 证书数据可以通过 QSslConfiguration::addCaCertificate() 和 QSslConfiguration::addCaCertificates() 扩展和定制。
\end{compactitem}

要扩展在 SSL 握手期间 SSL 套接字使用的默认 CA 证书列表，您必须像下面的代码片段一样更新默认配置：

\begin{cppcode}
 QList<QSslCertificate> certificates = getCertificates();
 QSslConfiguration configuration = QSslConfiguration::defaultConfiguration();
 configuration.addCaCertificates(certificates);
 QSslConfiguration::setDefaultConfiguration(configuration);
\end{cppcode}

%%%%%%%%%%%%%%%%%%%%%%

\begin{notice}
在 Unix 系统（ macOS 除外）下，如果可能的话，QSslSocket 将从标准证书目录中按需加载根证书。
如果您不想按需家在根证书，则您需要在应用程序进行首次 SSL 握手之前（例如通过 QSslSocket::systemCaCertificates() 传递证书）

调用 QSslConfiguration::defaultConfiguration()::setCaCertificates() ，
或者在您的 QSslSocket 实例进行 SSL 握手前调用 Q
SslConfiguration::defaultConfiguration()::setCaCertificates()。
\end{notice}

您也可以在 QSslCipher 和 QSslCertificate 类文档中找到关于密钥与证书的信息。

该产品包括了由 OpenSSL Project 项目开发的，可在 OpenSSL Toolkit 工具包中使用的软件 (http://www.openssl.org/) 。

\begin{notice}
要注意 bytesWritten() 信号和 encryptedBytesWritten() 信号之间的差别。 
对于 QTcpSocket 类来说，一旦数据被写入到 TCP 套接字， bytesWritten() 信号就会被发出。 

对 QSslSocket 类来说，当数据正在被加密时，bytesWritten() 信号将会被发出；
当数据写入到 TCP 套接字后，encryptedBytesWritten() 信号将会被发出。
\end{notice}

\begin{seeAlso}
QSslCertificate，QSslCipher 和 QSslError。
\end{seeAlso}

\section{成员类型文档}

enum QSslSocket::PeerVerifyMode

描述了 QSslSocket 的对等端验证模式。默认模式为 自动验证对等端 (AutoVerifyPeer)，
该模式下将会根据 QSslSocket::SslMode 选择一个合适的验证模式 。

\begin{tabular}[l]{|l|l|m{28em}|}
	\hline 
	常量 	& 值  &	描述 \\
	\hline
	QSslSocket::VerifyNone &	0 &	QSslSocket 将不会请求对等端发送证书。
	  如果您对连接的另一端的身份并不感兴趣，您可以使用该模式。
	  连接依旧会被加密，如果对等端需要您的本地证书，套接字仍然会发送本地套接字到对等端。 \\ 
	\hline
	QSslSocket::QueryPeer& 	1 	&QSslSocket 将会请求对等端发送一个证书，
	但是并不需要该证书有效。如果您想向用户展示对等端证书的详细信息，
	但是并不象影响实际的 SSL 握手，可以考虑使用该模式。
	该模式是服务器的默认模式。注意：在频道(Schannel)中该值与 QSslSocket::VerifyNone 效果相同。 \\
	\hline
	QSslSocket::VerifyPeer &	2 &	This mode is the default for clients.QSslSocket 将在握手阶段请求对等端发送一个有效的证书。
	如果失败，QSslSocket 将会发送 QSslSocket::sslErrors() 信号。 \\ 
	\hline
	QSslSocket::AutoVerifyPeer 	&3 &	QSslSocket will automatically use QueryPeer for server sockets and VerifyPeer for client sockets.自动模式。
	服务端 QSslSocket 会自动使用 QueryPeer 模式，客户端 QSslSocket 会自动使用 AutoVerifyPeer 模式。 \\ 
	\hline
\end{tabular}


该枚举最初在 Qt 4.4 引入。

\begin{seeAlso}
QSslSocket::peerVerifyMode()。
\end{seeAlso}

enum QSslSocket::SslMode

描述了 QSslSocket 可用的连接模式。


\begin{tabular}[l]{|l|l|m{28em}|}
	\hline 
	常量 	& 值  &	描述 \\
	\hline
QSslSocket::UnencryptedMode  &	0 &	未加密套接字，该行为与 QTcpSocket 相同。 \\ 
\hline
QSslSocket::SslClientMode &	1 	&该套接字为客户端 SSL 套接字。它既可以已经被加密，也可以处于握手阶段（详情见 QSslSocket::isEncrypted() ）。 \\ 
\hline
QSslSocket::SslServerMode &	2 	&该套接字为服务端 SSL 套接字。它既可以已经被加密，也可以处于握手阶段（详情见 QSslSocket::isEncrypted() ）。 \\ 
	\hline
\end{tabular}

\section{成员函数文档}

QSslSocket::QSslSocket(QObject \emph{*parent} = nullptr)

构造一个 QSslSocket 对象。
parent 参数将传递给 QObject 构造函数。
新套接字的密钥套件设置为静态方法 defaultCiphers() 返回的一个密钥。

[signal] void QSslSocket::encrypted()

当 QSslSocket 进入加密模式时将发出该信号。该信号发送后， 
QSslSocket::isEncrypted() 将会返回 true，并且接下来套接字上的传输都将被加密。

\begin{seeAlso}
QSslSocket::connectToHostEncrypted() 和 QSslSocket::isEncrypted()。
\end{seeAlso}


[signal] void QSslSocket::encryptedBytesWritten(qint64 \emph{written})

当 QSslSocket 将加密数据写入到网路后将会发出该信号。
 written 参数包含着成功写入的字节书。

该函数最初在 Qt 4.4 版本引入。

\begin{seeAlso}
QIODevice::bytesWritten()。
\end{seeAlso}

[slot] void QSslSocket::ignoreSslErrors()

该函数会让 QSslSocket 忽略握手期间的错误并继续连接。
如果您想要让 QSslSocket 在握手期间即使出现错误仍继续链接，
您必须在链接到 sslErrors() 信号的槽函数中调用该槽函数或者在握手阶段之前调用该槽函数。
如果您不调用该函数，在 sslErrors() 信号发送后，无论是在回应错误期间还是在握手期间之前，
连接都会断开。

如果 SSL 握手期间没有发生任何错误（即对等端的身份成功建立），
QSslSocket 不会发送 sslErrors() 信号，因而在此时调用该函数是没有任何必要的。

\begin{warning}
确保始终让用户检查 sslErrors() 信号报告的错误，
并且仅在用户确认可以继续进行操作时才调用此方法。如果发生了以外的错误，连接应当被取消。
未经检查实际的错误就盲目的调用该函数会给您的应用程序带来极大的安全隐患。请谨慎使用该函数！
\end{warning}

\begin{seeAlso}
sslErrors()。
\end{seeAlso}

[signal] void QSslSocket::modeChanged(QSslSocket::SslMode \emph{mode})

当 QSslSocket 从 QSslSocket::UnencryptedMode 
模式变为 QSslSocket::SslClient 模式或者 
QSslSocket::SslServerMode 模式后会发出该信号。 参数 mode 即新的模式。

\begin{seeAlso}
mode()。
\end{seeAlso}

[signal] void QSslSocket::newSessionTicketReceived()

如果在握手期间协商了 TLS 1.3 协议，QSslSocket 会在接收到新的会话票据（ SessionTicket ）后发送该信号。
会话和会话票据的生命周期的示意会在套接字的配置中更新。该会话可用于将来的 TLS 连接中的会话恢复（和缩短的握手）。

\begin{notice}
该功能仅支持 OpenSSL 后端，并要求 OpenSSL 版本 1.1.1及以上。
\end{notice}

该函数最初在 Qt 5.15 版本引入。

\begin{notice}
QSslSocket::sslConfiguration()，QSslConfiguration::sessionTicket() 和 QSslConfirguration::sessionTicketLifeTimeHint()。
\end{notice}

[signal] void QSslSocket::peerVerifyError(const QSslError \emph{\&error})

QSslSocket 在握手期间、加密连接建立之前，
可以多次发出该信号来表明对等端身份建立时出现错误。
error 参通常表示了 QSslSocket 不能安全地鉴定对等端身份。

当遇到问题时该信号会给你提供早期的指示。通过连接该信号，您可以在连接的槽函数中在握手完成前手动结束该连接。
如果该信号发送后未采取任何操作， QSslSocket 会继续发送 QSslSocket::sslErrors() 信号。

该函数最初在 Qt 4.4 版本引入。

另外您也可以在 sslErrors() 函数介绍中找到相关信息。

[signal] void QSslSocket::preSharedKeyAuthenticationRequired(QSslPreSharedKeyAuthenticator \emph{*authenticator})

QSslSocket 在协商 PSK 密码套件时发出此信号，并且接下来会要求 PSK 身份验证。

当使用 PSK 时，为了使 SSL 握手继续执行，
客户端必须向服务端发送一个有效的身份证明和一个有效的预分享密钥。
应用程序可以通过一个连接到该信号的槽函数提供这些信息，
根据他们的需求来填充传输的 authenticator 对象。

\begin{notice}
忽略该信号或者提供信用材料失败会造成握手失败，该连接也会因而被取消。
\end{notice}

\begin{notice}
authenticator 对象由该套接字所有并且不能被应用程序删除。
\end{notice}

该函数最初在 Qt 5.5 版本引入。

\begin{seeAlso}
QSslPreSharedKeyAuthenticator。
\end{seeAlso}

[signal] void QSslSocket::sslErrors(const QList<QSslError> \&errors)

在握手期间，QSslSocket 会发送该信号表明在建立对等端身份鉴定的时候出现了一个或者多个错误。
这些错误通常表明 QSslSocket 不能安全的鉴定对等端的身份。
除非采取相关的操作，否则该连接将会在该信号发出后断开。

如果您想要忽略发生的错误并继续连接，您必须在连接到该信号的槽函数中调用 QsslSocket::ignoreSslErrors() 函数。
如果您想要在稍后获得错误列表，您可以调用 sslHandshakeErrors() 函数。

error 参数包括着一个或者多个阻止 QSslSocket 验证对等端身份的错误。

\begin{notice}
连接该信号时，您不能使用 Qt::QueuedConnection 方式，
否则调用 QsslSocket::ignoreSslErrors() 函数将不会起任何作用。
\end{notice}

\begin{notice}
信号 sslErrors 在该类中被重载。
\end{notice}

为了通过使用函数指针连接到该信号，Qt 提供了一个便捷的助手来包含函数指针，示例如下：

\begin{cppcode}
connect(sslSocket, QOverload<const QList<QSslError> &>::of(&QSslSocket::sslErrors),
     [=](const QList<QSslError> &errors){ /* ... */ });
\end{cppcode}

\begin{seeAlso}
peerVerifyError()。
\end{seeAlso}

[slot] void QSslSocket::startClientEncryption()

为客户端连接开启一个 SSL 延迟握手。
您可以在套接字处于已连接且仍然处于未加密模式时调用该槽函数。
如果该套接字处于未连接状态或者该套接字已经进入加密模式，则该函数将不会生效。

重新实现了 STARTTLS 的客户端经常会利用延迟 SSL 握手。
其他大部分客户端可以使用 connectToHostEncrypted() 函数来替代该函数，
connectToHostEncrypted() 函数将会自动执行握手。

[slot] void QSslSocket::startServerEncryption()

为服务端连接开启延迟 SSL 握手。您可以在套接字处于已连接且仍然处于未加密模式时调用该槽函数。
如果该套接字处于未连接状态或者该套接字已经进入加密模式，则该函数将不会生效。

对于服务端套接字来说，调用该函数是初始化 SSL 握手的唯一方式。
大多数服务端会在接收到一个连接、或者接收到一个进入 SSL 模式的指定协议指令
（例如：服务端接收到 "STARTTLS\\r\\n"）时，立即调用该函数。

实现一个 SSL 服务器最常用的的方式是创建一个 QTcpServer 并且重新实现 QTcpServer::incomingConnection() 函数。
将返回的套接字描述符传递给 QSslSOcket::setSocketDescriptor()。

\begin{seeAlso}
connectToHostEncrypted() 和 startClientEncryption()。
\end{seeAlso}

[virtual] QSslSocket::$\sim$QSslSocket()

析构函数。销毁 QSslSocket 对象。

void QSslSocket::abort()

关闭连接并将套接字重新初始化。
不像 disconnectFromHost() 函数，该还书会立即关闭套接字，并清空任何在写入缓冲区的数据。

\begin{seeAlso}
disconnectFromHost() 和 close()。
\end{seeAlso}

[override virtual] bool QSslSocket::atEnd() const

重新实现：QAbstractSocket::atEnd() 。

[override virtual] qint64 QSslSocket::bytesAvailable() const

重新实现：QAbstractSocket::bytesAvailable()。

返回可以立即读取的已解密数据的字节数。

[override virtual] qint64 QSslSocket::bytesToWrite() const

重新实现：QAbstractSocket::bytesToWrite()。

返回等待被加密和写入到网络的未加密数据的字节数。

[override virtual] bool QSslSocket::canReadLine() const

重新实现：QAbstractSocket::canReadLine()。

若能读取一行已解密的数据（以一个 ASCII 字符 '\\n' 结束 ）则返回 true，否则返回 false 。

[override virtual] void QSslSocket::close()

重新实现：QAbstractSocket::close()。

void QSslSocket::connectToHostEncrypted(const QString \&hostName, quint16 port, QIODevice::OpenMode mode = ReadWrite, QAbstractSocket::NetworkLayerProtocol protocol = AnyIPProtocol)

使用 mode 指定的 OpenMode，在 hostName 指定的主机的 port 指定的端口上启动一个加密连接。该函数的作用与调用 connectToHost() 函数建立连接然后使用 startClientEncryption() 函数相同。protocol 参数可以用来指定网络协议（例如 IPv4 或者 IPv6）。

QSslSocket 首先会进入查询主机（HostLookupState）状态。然后，套接字会进入事件循环或者一个 waitFor...() 函数，进入连接中（ConnectingState）状态，连接成功后，套接字会发出 connected() 信号。紧接着套接字会初始化 SSL 客户端握手。每次状态发生改变后， QSslSocket 都会发出 stateChanged() 信号。

初始化 SSL 客户端握手后，若对等端身份认证未能成功建立，套接字将会发出 sslErrors() 信号。
如果你想忽略出现的错误并继续连接，您必须在连接到 sslErrors() 
信号的槽函数中或者在进入加密模式之前调用 ignoreSslErrors() 函数。
如果没有调用 ignoreSslErrors() 函数，该连接将会断开，
并发出 disconnected() 信号，返回到未连接（UnconnectedState）状态。

若 SSL 握手连接建立成功，套接字将会发出 encrypted() 信号。

\begin{cppcode}
QSslSocket socket;
connect(&socket, SIGNAL(encrypted()), receiver, SLOT(socketEncrypted()));

socket.connectToHostEncrypted("imap", 993);
socket->write("1 CAPABILITY\r\n");
\end{cppcode}

\begin{notice}
上面的例子中文本可以在请求加密连接之后、 encrypted() 信号发出之前立即写入套接字中。
在这种情况下，文本将会在对象中队列，并在连接建立且 encrypted() 信号发出后写入到套接字中。
\end{notice}

mode 参数的默认值为读写 （ReadWrite）。

如果您想在服务器端创建一个 QSslSocket，您应该在 QTcpServer 接收到新接入连接后调用 startServerEncryption() 函数。

\begin{seeAlso}
connectToHost()，startClientEncryption() ，waitForConnected() 和 waitForEncrypted()。
\end{seeAlso}


void QSslSocket::connectToHostEncrypted(const QString \&hostName, quint16 port, const QString \&sslPeerName, QIODevice::OpenMode mode = ReadWrite, QAbstractSocket::NetworkLayerProtocol protocol = AnyIPProtocol)

重载函数。

与非重载版本的 connectToHostEncrypted 相比，该重载方法允许使用 sslPeerName 指定的证书服务器。

该函数最初在 Qt 4.6 版本引入。

另外您也可以在 connectToHostEncrypted() 函数介绍中找到相关信息。

qint64 QSslSocket::encryptedBytesAvailable() const

返回等待解密的数据的字节数。通常来说，在 QSslSocket 接收到数据便立即解密的情况下，该函数会返回 0。

该函数最初在 Qt 4.4 版本引入。

qint64 QSslSocket::encryptedBytesToWrite() const

返回等待加密的准备写入网络的数据的字节数。

该函数最初在 Qt 4.4 版本引入。

bool QSslSocket::flush()

该函数会在不引起阻塞的情况下 ，尽量多地往内部写缓冲区写入数据。
若写入了任何数据，该函数将会返回 true ，否则返回 false 。

如果您想要立即发送缓冲的数据，您可以调用此函数。可成功写入的数据的字节数取决于操作系统。
在大多情况下您并不需要调用此函数，因为 QAbstractSocket 会在重获事件循环控制权后会自动开始发送数据。
在没有事件循环情况下，请调用 waitForBytesWritten()。

\begin{seeAlso}
write() 和 waitForBytesWritten()。
\end{seeAlso}

void QSslSocket::ignoreSslErrors(const QList<QSslError> \&errors)

重载函数。

该方法可令 QSslSocket 仅忽略 errors 指定的错误。

\begin{notice}
因为大部分的 SSL 错误都与一个证书相关联，因而对于大多数 SSL 错误您都必须设置一个相关的预期证书。
\end{notice}

例如，如果要连接到使用自签名证书的服务器，请考虑使用以下代码段：

\begin{seeAlso}
 QList<QSslCertificate> cert = QSslCertificate::fromPath(QLatin1String("server-certificate.pem"));
 QSslError error(QSslError::SelfSignedCertificate, cert.at(0));
 QList<QSslError> expectedSslErrors;
 expectedSslErrors.append(error);

 QSslSocket socket;
 socket.ignoreSslErrors(expectedSslErrors);
 socket.connectToHostEncrypted("server.tld", 443);
\end{seeAlso}

对该函数的多次调用会替换掉先前调用该函数时传入的错误列表。若您想清空忽略错误的列表，您可以将一个空列表作为参数调用该函数。

\begin{notice}
sslErrors() 和 sslHandshakeErrors()。
\end{notice}

bool QSslSocket::isEncrypted() const

若该套接字已加密，则返回 true ，否则返回 false。

一个已加密的套接字会将由 write() 函数和 putChar() 函数写入的数据在写入前全部加密，
并在调用 read() 函数和 readLine() 函数或者 getChar() 函数前，
将从网络中接收的数据解密。

在进入加密模式后， QSslSocket 会发送 encrypted() 信号。

您可以调用 sessionCipher() 函数来查看加密和解密数据使用的密码。

\begin{notice}
mode()。
\end{notice}

QSslCertificate QSslSocket::localCertificate() const

返回套接字的本地证书，若未指定本地证书则返回一个空证书。

\begin{notice}
setLocalCertificate() 函数和 privateKey()。
\end{notice}

QList<QSslCertificate> QSslSocket::localCertificateChain() const

返回套接字的本地证书链，若未指定本地证书则返回一个空的列表。

该函数最初在 Qt 5.1 版本引入。

\begin{notice}
setLocalCertificateChain()。
\end{notice}

QSslSocket::SslMode QSslSocket::mode() const

返回该套接字当前的模式。当 QSslSocket 与 QTcpSocket 的行为相同，
则为 未加密 （UnencryptedMode） 模式。
当处于加密模式，则为 客户端 （SslClientMode）和 服务端 （SslServerMode）模式之一。

当模式发生改变，QSslSocket 会发出 modeChanged() 信号。
QVector<QOcspResponse> QSslSocket::ocspResponses() const

此函数返回使用 OCSP 的服务器在 TLS 握手期间可能发送的联机证书状态协议响应。 如果没有确定的响应或根本没有响应，则返回的 QVector 容器为空。

该函数最早在 Qt 5.13 引入。


\begin{notice}
QSslConfiguration::setOcspStaplingEnabled()。
\end{notice}

QSslCertificate QSslSocket::peerCertificate() const

返回对等端的数字证书（即您所连接到的主机的即时证书），若对等端未签署证书则返回一个空证书。

在握手阶段对等端证书会被自动检查，
所以该函数通常用来抓取证书以向用户展示或者诊断连接。
返回的证书包含着对等端的主机名、证书发行者和对等端公钥等对等端信息。

因为对等端证书是在握手阶段设置的，
因而在连接到 sslErrors() 和 encrypted() 信号的槽函数中获取对等端证书的行为是安全的。

如果该函数返回了一个空证书，则意味着 SSL 握手失败，
或者也意味着你链接到的主机并没有证书，或者您甚至没有建立一个连接。

如果您想要检查对等端完整的证书链，
您可以调用 peerCertificateChain() 函数来一次性获取所有的证书链。

\begin{notice}
peerCertificateChain()。
\end{notice}

QList<QSslCertificate> QSslSocket::peerCertificateChain() const

返回对等端的数字证书链，或者返回一个空的证书列表。

在握手阶段对等端证书会被自动检查，所以该函数通常用来抓取证书以向用户展示或者诊断连接。返回的证书包含着对等端的主机名、证书发行者和对等端公钥等对等端信息。

因为对等端证书是在握手阶段设置的，因而在连接到 sslErrors() 和 encrypted() 信号的槽函数中获取对等端证书的行为是安全的。

如果该函数返回了一个空的证书列表，则意味着 SSL 握手失败，或者也意味着你链接到的主机并没有证书，或者您甚至没有建立一个连接。

如果您仅想获得对等端的即时证书，请使用 peerCertificate() 函数。

\begin{notice}
peerCertificate()。
\end{notice}

int QSslSocket::peerVerifyDepth() const

返回对等端的证书链在 SSL 握手阶段要检查的最大的证书数目。若没有设置最大值，则返回0（意味着将会检查正歌证书链）。

证书将会以发行顺序检查，首先检查对等端私有证书，紧接着检查发行者证书，然后继续检查。

该函数最初在 Qt 4.4 版本引入。

\begin{notice}
setPeerVerifyDepth() 和 peerVerifyMode()。
\end{notice}

QSslSocket::PeerVerifyMode QSslSocket::peerVerifyMode() const

返回套接字的验证模式。该模式决定 QSslSocket 是否应当从对等端请求一个证书（即客户端从服务器请求一个证书或服务端从客户端请求一个整数），
以及它所请求的证书是否必须使有效的。

默认的模式时 AutoVerifyPeer，该模式下 QSslSocket 将为客户端使用 VerifyPeer，为服务端使用 QueryPeer。

该函数最初在 Qt 4.4 版本引入。

\begin{notice}
setPeerVerifyMode() ， setPeerVerifyDepth() 和 mode() 。
\end{notice}

QString QSslSocket::peerVerifyName() const

返回由 setPeerVerifyName() 设置的或者 connectToHostEncrypted() 函数提供的证书有效性检验信息的主机别名。

该函数最初在 Qt 4.8 版本引入。

\begin{notice}
setPeerVerifyName() 和 connectToHostEncrypted()。
\end{notice}

QSslKey QSslSocket::privateKey() const

返回套接字的私钥。

\begin{notice}
setPrivateKey() 和 localCertificate()。
\end{notice}

QSsl::SslProtocol QSslSocket::protocol() const

返回套接字的 SSL 协议。默认将使用 QSsl::SecureProtocols 协议。

\begin{notice}
setProtocol()。
\end{notice}

[override virtual protected] qint64 QSslSocket::readData(char *data, qint64 maxlen)

重新实现： QAbstractSocket::readData(char *data, qint64 maxSize)。

[override virtual] void QSslSocket::resume()

重新实现：QAbstractSocket::resume()。

在套接字数据传输暂停后继续数据传输。
如果该套接字调用了 setPauseMode(QAbstractSocket::PauseOnSslErrors) 并且发出了 sslErrors() 信号，
则为了使套接字继续传输必须调用此函数。

该函数最初在 Qt 5.0 版本引入。

\begin{notice}
QAbstractSocket::pauseMode() 和 QAbstractSicket::setPauseMode()。
\end{notice}

void QSslSocket::setPeerVerifyMode(QSslSocket::PeerVerifyMode mode)

将套接字的检验模式设置为 mode 参数指定的模式。该模式决定 QSslSocket 是否应当从对等端请求一个证书（即客户端从服务器请求一个证书或服务端从客户端请求一个整数），以及它所请求的证书是否必须使有效的。

默认的模式时 AutoVerifyPeer，该模式下 QSslSocket 将为客户端使用 VerifyPeer，为服务端使用 QueryPeer。

在进入加密模式后，设置模式并不会影响当前连接。

\begin{notice}
peerVerifyMode() ， setPeerVerifyDepth() 和 mode()。
\end{notice}

